home *** CD-ROM | disk | FTP | other *** search
/ Power CD-ROM!! 8 / Power CD-ROM 8.iso / prgmming / maxlib10 / pbfiles / pbfiles.doc < prev    next >
Encoding:
Text File  |  1994-10-14  |  69.6 KB  |  2,041 lines

  1.  
  2.  
  3.  
  4.  
  5.                    PBFILES.DOC
  6.                    ─────────────────────────────
  7.                    Documentation for PBFILES.ASM
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.                                   Copyright 1994 Brian McLaughlin
  19.                      ────────────────────────────────────────────
  20.                                               All Rights Reserved
  21.  
  22.  
  23.  
  24.  
  25.  
  26.                          TABLE OF CONTENTS
  27.  
  28.                                                       line number
  29.  
  30.       INTRODUCTION .....................................   83
  31.  
  32.          About MAXLIB For PB ...........................  121
  33.          Packing List ..................................  192
  34.          Requirements for Using PBFILES.................  212
  35.          PBFILES On A Network ..........................  232
  36.          Limited Warranty ..............................  243
  37.  
  38.       HOW TO USE PBFILES
  39.  
  40.          Using $LINK and $INCLUDE ......................  273
  41.          About File Handles ............................  316
  42.          About File Pointers ...........................  345
  43.          Example Code ..................................  460
  44.          Handling Errors ...............................  600
  45.          DOS Error Codes ...............................  729
  46.          About DOS STDxxx Devices ......................  762
  47.          Avoiding Problems with HUGE Arrays ............  835
  48.  
  49.       PBFILES REFERENCE ................................  947
  50.  
  51.          ClipF .........................................  996
  52.          CloseF ........................................ 1035
  53.          EndF% ......................................... 1058
  54.          ErrorCode% .................................... 1092
  55.          FlushF ........................................ 1119
  56.          GetF .......................................... 1149
  57.          GetLineF$ ..................................... 1216
  58.          GetLocF& ...................................... 1274
  59.          GetPtrBase% ................................... 1308
  60.          GetStF ........................................ 1350
  61.          HandleF% ...................................... 1396
  62.          KillF ......................................... 1424
  63.          LoadF ......................................... 1451
  64.          OpenF% ........................................ 1497
  65.          PutF .......................................... 1552
  66.          PutStF ........................................ 1612
  67.          SaveF ......................................... 1650
  68.          SaveLineF ..................................... 1696
  69.          SetAccessCode ................................. 1754
  70.          SetBufferSize ................................. 1798
  71.          SetErrorCode .................................. 1840
  72.          SetLocF ....................................... 1864
  73.          SetPtrBase .................................... 1916
  74.          SizeF& ........................................ 1958
  75.  
  76.       WHY THIS FILE IS COPYRIGHTED ..................... 1987
  77.  
  78.       LIMITED DISTRIBUTION LICENSE ..................... 2012
  79.  
  80.  
  81.  
  82.  
  83.     INTRODUCTION
  84.  
  85.  
  86.     The routines in PBFiles grew out of my frustration with the file
  87.     i/o commands QuickBASIC 4.5.  When PowerBASIC 3.0 was released I
  88.     adapted my code for use with that compiler.
  89.  
  90.     With PBFiles you do not need to use ON ERROR to handle file i/o
  91.     errors.  Instead, you have complete control over when, where and
  92.     how your program polls for errors.
  93.  
  94.     PBFiles traps critical errors, so your program won't be
  95.     interrupted by the DOS critical error handler and its infamous
  96.     "Abort, Retry, Fail..." message.
  97.  
  98.     With PBFiles you can read to or write from almost any variable
  99.     type or array, with the only limit on the number of bytes you
  100.     can move at a single call being the largest block of addressable
  101.     RAM.
  102.  
  103.     With PBFiles you can read from or write to any segment in
  104.     memory, without the 64K limit of BSAVE and BLOAD and without a
  105.     header being attached to your file.  If you are saving video
  106.     RAM, you can put any number of screens in a single file and
  107.     access them in any order.
  108.  
  109.     I have placed the source code for PBFiles (PBFILES.ASM) into the
  110.     public domain, so now you can have this power and simplicity in
  111.     your programs - for free.
  112.  
  113.     Please note that the file you are reading (PBFILES.DOC) is
  114.     copyrighted and can only be reproduced according to the terms
  115.     outlined in LIMITED DISTRIBUTION LICENSE, at the end of this
  116.     file.
  117.  
  118.  
  119.  
  120.  
  121.     ABOUT MAXLIB FOR PB
  122.  
  123.  
  124.     If you like PBFiles, you may be interested in a shareware
  125.     library of routines I have developed, called MAXLIB For PB.
  126.  
  127.     MAXLIB for PB v1.0 consists of two complete sets of routines:
  128.     MAXFiles and MAXArray.  Together they give you the first really
  129.     painless way to add EMS memory management to your programs!
  130.  
  131.     Most of the 25 commands in MAXFiles are duplicates of the
  132.     commands in PBFiles, so that your code can be easily translated
  133.     from PBFiles to MAXFiles.  MAXFiles speeds up your program's
  134.     disk file access by loading disk files into expanded memory as
  135.     they are opened.  From then on, your program will read from and
  136.     write to the file in expanded memory, which is much faster than
  137.     if the file were accessed directly from the disk.
  138.  
  139.     MAXFiles takes advantage of whatever expanded memory is
  140.     available (if any) and will automatically fall back to using
  141.     disk space when expanded memory is exhausted.  For that reason,
  142.     programs written using MAXFiles can run on computers with no
  143.     expanded memory, or with very little, or a lot -- all using the
  144.     same few lines of code!
  145.  
  146.     The 16 commands in MAXArray are patterned after the BASIC
  147.     commands used to dimension and manage arrays in conventional
  148.     memory.  With MAXArray you can create and manage arrays that are
  149.     much larger than 640K -- right up to the limit of available EMS
  150.     memory, without having to learn all the intricacies of expanded
  151.     memory management.
  152.  
  153.     MAXArray lets you copy entire files or conventional arrays into
  154.     and out of expanded memory using a single line of code!  And
  155.     because it has less internal complexity, MAXArray is even faster
  156.     than MAXFiles.
  157.  
  158.     It is my hope that MAXLIB For PB will become widely available
  159.     through normal channels of shareware distribution, such as
  160.     BBSes, CD-ROMs and disk swapping among users.  But if you can't
  161.     find a copy, you can order your evaluation copy of MAXLIB for PB
  162.     this way:
  163.  
  164.       1) Send $5 to cover shipping and handling if you live in the
  165.          USA, or $8 if you live outside the USA.  (You must send $US
  166.          funds or a check drawn on a US bank.)
  167.  
  168.       2) INCLUDE YOUR ADDRESS (!) and whether you want 3.5" or 5.25"
  169.          disks.  If you omit the disk size I will send 3.5".  All
  170.          disks will be DS/DD.
  171.  
  172.       3) Be sure to note that you want the PB3 version (other
  173.          versions are planned for other compilers.)
  174.  
  175.       4) Send all of the above to:
  176.  
  177.                   Brian McLaughlin
  178.                   MAXLIB for PB Trial Disk
  179.                   PO Box 2131
  180.                   Lake Oswego, OR  97035
  181.                   USA
  182.  
  183.  
  184.       5) The copy you receive will be for evaluation purposes only.
  185.          Full registration is required before you can distribute any
  186.          programs incorporating MAXLIB For PB.
  187.  
  188.  
  189.  
  190.  
  191.  
  192.     PACKING LIST
  193.  
  194.  
  195.     For this copy of PBFILES.DOC to be legal, you should have ALL of
  196.     the following files (at least):
  197.  
  198.  
  199.        PBFILES.DOC   -- the file you are reading
  200.        PBFILES.ASM   -- the source code for PBFiles
  201.        PBFILES.OBJ   -- the object file assembled from PBFILES.ASM
  202.        PBFILES.BI    -- the DECLARE statements for PBFiles
  203.  
  204.  
  205.     If all of these files are not present, then this copy of
  206.     PBFILES.DOC is illegal and it should not be copied or
  207.     distributed.  (See the section: LIMITED DISTRIBUTION LICENSE)
  208.  
  209.  
  210.  
  211.  
  212.     REQUIREMENTS FOR USING PBFILES
  213.  
  214.  
  215.     To use PBFiles you will need the file PBFILES.OBJ and the
  216.     compiler PowerBASIC 3.0b or later.  I have tested PBFILES with
  217.     PowerBASIC 3.0a and there are bugs in that compiler which make
  218.     PBFILES unstable.  PowerBASIC is a trademark of PowerBASIC, Inc.
  219.     of Carmel, California.
  220.  
  221.     An assembler is optional.  You do not need to know or understand
  222.     assembly language to use PBFiles.
  223.  
  224.     PBFiles is written in 8086 assembly language, so it will run on
  225.     any 80x86-based DOS computer.  PBFiles uses DOS services that
  226.     are present in every version of DOS numbered 2.1 or better.
  227.  
  228.  
  229.  
  230.  
  231.  
  232.     PBFILES ON A NETWORK
  233.  
  234.  
  235.     Although PBFiles provides some support for networks, it has not
  236.     been tested in a networked environment.  If you use PBFiles in a
  237.     network, you should test it thoroughly, until you are satisfied
  238.     it is safe.
  239.  
  240.  
  241.  
  242.  
  243.     LIMITED WARRANTY
  244.  
  245.  
  246.     Please read the following warranty carefully:
  247.  
  248.     THIS COPY OF PBFILES (THE "SOFTWARE") IS PROVIDED ON AN "AS IS"
  249.     BASIS.  BRIAN MCLAUGHLIN (THE "AUTHOR") DISCLAIMS ALL WARRANTIES
  250.     RELATING TO THE SOFTWARE, WHETHER EXPRESSED OR IMPLIED,
  251.     INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF
  252.     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  NEITHER
  253.     THE AUTHOR NOR ANYONE ELSE WHO HAS BEEN INVOLVED IN THE
  254.     CREATION, PRODUCTION, OR DELIVERY OF THE SOFTWARE SHALL BE
  255.     LIABLE FOR ANY INDIRECT, CONSEQUENTIAL, OR INCIDENTAL DAMAGES
  256.     ARISING OUT OF THE USE OR INABILITY TO USE SUCH SOFTWARE, EVEN
  257.     IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  258.     DAMAGES OR CLAIMS.  THE PERSON USING THE SOFTWARE BEARS ALL RISK
  259.     AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE.
  260.  
  261.  
  262.  
  263.  
  264.     HOW TO USE PBFILES
  265.  
  266.  
  267.     This section contains enough information to get you started
  268.     using PBFiles.  More detailed information is available in the
  269.     PBFILES REFERENCE section.
  270.  
  271.  
  272.  
  273.     USING $LINK AND $INCLUDE
  274.  
  275.  
  276.     Every program that uses PBFiles must meet a few simple
  277.     requirements: it must make the object file PBFILES.OBJ available
  278.     to the PB compiler, and it must include declarations for all the
  279.     routines it uses from PBFiles.
  280.  
  281.     By far the easiest way to meet these requirements is to add two
  282.     simple lines of code near the beginning of your source code.
  283.     The first line uses the $LINK metacommand to incorporate
  284.     PBFILES.OBJ into your program.  You must place this line before
  285.     any executable commands in your source code:
  286.  
  287.  
  288.         $LINK "PBFILES.OBJ"
  289.  
  290.  
  291.     If PBFILES.OBJ is not in the current directory, you must tell PB
  292.     how to find it by including the full path in the the file spec.
  293.     For instance, if it were on a RAM disk designated as your D:
  294.     drive, in a subdirectory named LIB, the full file spec would be:
  295.  
  296.  
  297.         $LINK "D:\LIB\PBFILES.OBJ"
  298.  
  299.  
  300.     You will also need to include a second line near the top of your
  301.     source code:
  302.  
  303.  
  304.         $INCLUDE "PBFILES.BI"
  305.  
  306.  
  307.     PBFILES.BI contains the declarations for all the routines in
  308.     PBFiles.  The above line of code above includes those
  309.     declarations in your code.  Again, if PBFILES.BI is not in the
  310.     current directory, you will need to let PB know how to find it
  311.     by including the full path in the file spec.
  312.  
  313.  
  314.  
  315.  
  316.     ABOUT FILE HANDLES
  317.  
  318.  
  319.     File handles are a lot like file numbers.  In BASIC you are
  320.     asked to give a file a number to identify it.  Which can be a
  321.     problem when you don't know what file numbers are already in
  322.     use, so you end up using this sort of code:
  323.  
  324.  
  325.        FNum% = FREEFILE
  326.        OPEN FileName$ FOR BINARY AS FNum%
  327.  
  328.  
  329.     Instead of requiring you to come up with your own file number,
  330.     PBFiles uses the DOS file handle.  Whenever DOS opens a file, it
  331.     issues the file a unique file "handle".  PBFiles simply passes
  332.     that handle along to your code:
  333.  
  334.  
  335.        Handle% = OpenF%(FileName$)
  336.  
  337.  
  338.     Just as most BASIC file commands want to know a file's number
  339.     instead of its name, most PBFiles commands want to know a file's
  340.     handle, not its name.
  341.  
  342.  
  343.  
  344.  
  345.     ABOUT FILE POINTERS
  346.  
  347.  
  348.     It is possible to program in BASIC without ever learning about
  349.     file pointers.  However, PBFiles requires that you understand
  350.     file pointers, so if you are unfamiliar with them, please read
  351.     this section.
  352.  
  353.     NOTE: DOS, PB and PBFiles all consider a file's first byte to be
  354.     byte zero rather than byte 1. Although PBFiles does let you
  355.     choose the one-based convention, this section will use the
  356.     zero-based convention throughout.
  357.  
  358.     Think of a file pointer as an invisible finger pointing at the
  359.     exact byte where PBFiles will begin to read from or write to a
  360.     file.  It will move itself as you read (or write), like a finger
  361.     following text on the page of a book.  As you stop reading (or
  362.     writing) the finger stops itself one byte beyond the most recent
  363.     byte read (or written).
  364.  
  365.     When a file is first opened the pointer is at the first byte of
  366.     the file: byte zero.  If you start writing to a file right after
  367.     opening it, you will start writing at byte zero.  And if any
  368.     data is in the file it will be overwritten by the new data,
  369.     starting with byte zero.
  370.  
  371.     Luckily, you can move the pointer anywhere you want, anytime you
  372.     want.  For the sake of simplicity, let's suppose you have a file
  373.     that is four bytes long and you want to append some data to the
  374.     end of this file.  The four bytes would run from zero to 3:
  375.  
  376.  
  377.        BYTES:  0  1  2  3
  378.                ^
  379.  
  380.     Since you have just opened the file, the pointer (^) is at byte
  381.     zero.  Before you can append data to the end of a file, the
  382.     pointer must point one byte beyond the file's last byte.  In
  383.     this case the last byte is byte 3, and one byte beyond byte 3 is
  384.     byte 4.
  385.  
  386.     To move a pointer for appending data, first you need to know how
  387.     long the file is.  In BASIC you could use LOF, but in PBFiles
  388.     you would use SizeF&, like so:
  389.  
  390.  
  391.        Handle% = OpenF%(FileName$)
  392.        Size& = SizeF&(Handle%)
  393.  
  394.  
  395.     In this case, Size& will equal 4, because our file is four bytes
  396.     long.  And, conveniently, the byte that is one byte past the end
  397.     is byte 4. You may move the pointer to byte 4, using SetLocF:
  398.  
  399.  
  400.        Size& = SizeF&(Handle%)    'Size& = 4
  401.        SetLocF Handle%, Size&     'pointer is at byte 4
  402.  
  403.  
  404.     Now our file looks like this:
  405.  
  406.  
  407.        BYTES:  0  1  2  3 (4)
  408.                            ^
  409.  
  410.     I put the 4 in parentheses because it really doesn't "belong to"
  411.     our file yet, even though the pointer points there.  Now, if we
  412.     write something to our file, no old data will be overwritten.
  413.  
  414.     Now let's write some data to our file and see what happens.  To
  415.     write data, you might use PUT in BASIC.  In PBFiles you might
  416.     use PutF.  This is how you'd write an integer to the file:
  417.  
  418.  
  419.        PutF Handle%, 2&, Variable%
  420.  
  421.  
  422.     This writes 2 bytes to the end of our file, so it looks like
  423.     this:
  424.  
  425.  
  426.        BYTES:  0  1  2  3  4  5  (6)
  427.                                   ^
  428.  
  429.     Now there are six bytes in our file (0-5) and the pointer has
  430.     moved to byte 6. The pointer moves each time we write OR read
  431.     bytes.  It moves exactly one byte forward for every byte we read
  432.     or write.
  433.  
  434.     Those last two sentences are VERY important:
  435.  
  436.     ** The pointer moves each time we write OR read bytes.  It moves
  437.     exactly one byte forward for every byte we read or write.  **
  438.  
  439.     If you do not know where the pointer is, you can get into big
  440.     trouble.  To avoid such trouble you can always ask where the
  441.     pointer is by calling GetLocF&.  Just remember that when
  442.     GetLocF& tells you the pointer is at byte 1, it is referring to
  443.     the second byte of the file.
  444.  
  445.     That covers all you need to know about file pointers.  All in
  446.     all, file pointers allow you to read or write anywhere you want
  447.     in a file.  You can open a file, read a few bytes, jump
  448.     somewhere, write over some other bytes, jump to the end, tack on
  449.     some bytes there, then jump back to the start - all without
  450.     having to close and reopen your file.
  451.  
  452.     You are not required to having same-length records.  You are not
  453.     required to start at the front and plow straight to the end.
  454.     You can order your data anyway you like and put it anywhere
  455.     that's convenient, just by jumping the pointer there.
  456.  
  457.  
  458.  
  459.  
  460.     EXAMPLE CODE
  461.  
  462.  
  463.     This example code can be cut and pasted into a separate file and
  464.     compiled inside the PB IDE.
  465.  
  466.     This code makes a temporary file, writes data to it from an
  467.     array, changes one element of the array, writes the old data
  468.     back from the file into the array, and then verifies that the
  469.     changed element has resumed its orginal value.  It then opens
  470.     this file (PBFILES.DOC) and reads the first few lines of the
  471.     file, printing them onto the screen.
  472.  
  473.     That's not much.  But it shows the general concepts you'll need.
  474.  
  475.  
  476.  
  477.     '***********************  START CODE *******************************
  478.  
  479.      $LINK "PBFILES.OBJ"             'assumes OBJ file in current dir
  480.      $INCLUDE "PBFILES.BI"           'contains the DECLARE statements
  481.      DECLARE SUB HandleError ()      'dummy error handler
  482.  
  483.      RANDOMIZE TIMER
  484.      SHARED Handle%                  'make this global
  485.  
  486.      PRINT "Filling array..."
  487.      DIM Test%(1 TO 1000)            'make a test array of integers
  488.        FOR X% = 1 TO 1000            'and fill it with values
  489.          Test%(X%) = X%              'from 1 to 1000
  490.        NEXT X%
  491.  
  492.      CLS
  493.      FileName$ = "PBFILES.DAT"                   'make a temporary file
  494.      IF LEN(DIR$(FileName$)) THEN KillF FileName$ ' kill any previous
  495.        IF ErrorCode% THEN HandleError             'check for error
  496.  
  497.      IF OpenF%(FileName$) THEN                   'open (create) the file
  498.         Handle% = HandleF%                       'assign handle variable
  499.         PRINT FileName$; " created."             'report success
  500.      ELSE                                        'or else
  501.         PRINT "Failed to create file."           'report failure
  502.         HandleError                              'and call error SUB
  503.      END IF
  504.  
  505.      Bytes& = 2000&                              '1000 * 2 bytes
  506.      PRINT FileName$; " length in bytes:"; SizeF&(Handle%)
  507.        IF ErrorCode% THEN HandleError            'check for error
  508.      PRINT "File pointer at"; GetLocF&(Handle%)
  509.        IF ErrorCode% THEN HandleError            'check for error
  510.  
  511.      PRINT
  512.      PRINT "About to write "; Bytes&; " bytes to "; FileName$
  513.      PutF Handle%, Bytes&, Test%(1)              'write 'em, cowboy!
  514.        IF ErrorCode% THEN HandleError            'check for error
  515.  
  516.      FlushF Handle%                              'flush the buffers
  517.        IF ErrorCode% THEN HandleError            'check for error
  518.  
  519.      PRINT FileName$; " length in bytes:"; SizeF&(Handle%)
  520.        IF ErrorCode% THEN HandleError            'check for error
  521.  
  522.      PRINT "File pointer at"; GetLocF&(Handle%)
  523.        IF ErrorCode% THEN HandleError            'check for error
  524.  
  525.      'Let's see if the data stays the same when written back from disk.
  526.  
  527.      RandElem% = RND * 1000
  528.      PRINT
  529.      PRINT "About to select a random array element and change it."
  530.      PRINT "Old value of random element:"; Test%(RandElem%)
  531.  
  532.      Test%(RandElem%) = (RND * 1000) + 1000
  533.      PRINT "New value of random element:"; Test%(RandElem%)
  534.  
  535.      SetLocF Handle%, 0&                         'move pointer to byte 0
  536.        IF ErrorCode% THEN HandleError            'check for error
  537.  
  538.      PRINT
  539.      PRINT "About to write original data back from file into array."
  540.      PRINT "Before writing from file, pointer at:"; GetLocF&(Handle%)
  541.  
  542.      GetF Handle%, Bytes&, Test%(1)              'write file to array
  543.        IF ErrorCode% THEN HandleError            'check for error
  544.  
  545.      PRINT "After writing from file, pointer at:"; GetLocF&(Handle%)
  546.      PRINT "Current value of element that was changed:"; Test%(RandElem%)
  547.      PRINT
  548.  
  549.      CloseF Handle%
  550.        IF ErrorCode% THEN HandleError
  551.      PRINT FileName$; " closed."
  552.  
  553.      KillF FileName$
  554.        IF ErrorCode% THEN HandleError
  555.      PRINT FileName$; " deleted."
  556.  
  557.      'Now let's open PBFILES.DOC and show a few lines of it.
  558.  
  559.      FileName$ = "PBFILES.DOC"      'assume file is in current directory
  560.  
  561.      IF LEN(DIR$(FileName$)) THEN                'try to find the file
  562.        IF OpenF%(FileName$) THEN                 'open PBFILES.DOC
  563.           Handle% = HandleF%                     'assign handle variable
  564.        ELSE                                      'or else
  565.           HandleError                            'call error SUB
  566.        END IF
  567.      ELSE
  568.        PRINT "Couldn't find PBFILES.DOC. Ending now."
  569.        END
  570.      END IF
  571.  
  572.      LOCATE 24, 1
  573.      PRINT "Press a key to see text from PBFILES.DOC..."
  574.      DO: LOOP UNTIL LEN(INKEY$)
  575.  
  576.      CLS
  577.      FOR X% = 1 TO 22                            'print 22 lines
  578.        PRINT GetLineF$(Handle%)
  579.        IF ErrorCode% THEN
  580.           HandleError
  581.        END IF
  582.      NEXT X%
  583.  
  584.      CloseF Handle%                              'close PBFILES.DOC
  585.      END
  586.  
  587.     '=================
  588.      SUB HandleError
  589.     '=================
  590.  
  591.       PRINT "An error occured. The error number was: "; ErrorCode%
  592.       PRINT "Aborting program now...."
  593.       END                        'ends program
  594.  
  595.     END SUB
  596.     '************************* END CODE ********************************
  597.  
  598.  
  599.  
  600.     HANDLING ERRORS
  601.  
  602.  
  603.     The usual method of error handling in BASIC requires that you
  604.     use some variation of the ON ERROR statement.  I have always
  605.     found ON ERROR to be cumbersome, code-bloating and difficult to
  606.     program.  Even PowerBASIC's own manual (p.288) suggests that you
  607.     consider using a third party library.
  608.  
  609.     I think you will find the error trapping in PBFiles to be simple
  610.     to use.  Whenever an error takes place (including critical
  611.     errors), the PBFiles routine that was running at the time of the
  612.     error will store the error code in an internal variable and
  613.     return directly to your program.
  614.  
  615.     Your program must test the value of this error code variable in
  616.     order to find out whether an error has occured.  PBFiles has a
  617.     routine called ErrorCode% for reporting the value of the
  618.     internal error code variable.
  619.  
  620.     The process of testing the value of an error code variable is
  621.     called polling.
  622.  
  623.  
  624.         Handle% = OpenF%(FileName$) IF ErrorCode% THEN CALL
  625.            HandleError...
  626.  
  627.  
  628.     In the above example, the code polls for an error directly after
  629.     opening a file, and if an error is reported the code calls a SUB
  630.     named HandleError.
  631.  
  632.     You can poll for errors as often or as seldom as you think
  633.     necessary.  If an error takes place in one routine and your
  634.     program calls several more routines before polling for an error,
  635.     the value of the error code variable will report the most recent
  636.     error to take place, if any.
  637.  
  638.     The internal error code variable is initialized to zero only
  639.     once, at the beginning of your program.  The value of this
  640.     variable will remain zero so long as no error takes place.
  641.  
  642.     However, when the first error takes place, the value of this
  643.     variable will change to reflect the error code, and it will
  644.     remain unchanged until one of two things intervenes to change
  645.     its value:
  646.  
  647.        1) another (different) error takes place, or
  648.        2) your program resets the value, using SetErrorCode.
  649.  
  650.  
  651.     SetErrorCode is similar to the function ERROR in BASIC.  You may
  652.     use it to clear the error code variable back to zero like this:
  653.  
  654.  
  655.        SetErrorCode 0
  656.  
  657.  
  658.     SetErrorCode may also be used to simulate errors (for example,
  659.     during the testing of your error handler) by passing non-zero
  660.     values corresponding to error codes.  The corresponding
  661.     error-reporting routine will report these values back to your
  662.     program as errors:
  663.  
  664.  
  665.        SetErrorCode 2
  666.        IF ErrorCode% THEN ....    'ErrorCode% always returns 2 here
  667.  
  668.  
  669.     A list of error codes and what they mean can be found in the
  670.     section DOS ERROR CODES, below.  You may also encounter one
  671.     non-standard error code: -1.  The -1 indicates that GetLineF$
  672.     was unable to allocate a string to use as a buffer.
  673.  
  674.     Because PBFiles requires your program to poll for errors, the
  675.     error handling in PBFiles is roughly the same as ON ERROR RESUME
  676.     NEXT used with ERR, in this fashion:
  677.  
  678.  
  679.         ON ERROR RESUME NEXT             'if error happens keep going
  680.         .
  681.         .
  682.         OPEN FileName$ FOR BINARY AS #1  'an error might happen here
  683.            IF ERR THEN                   'see if an error occured
  684.               CALL ErrorHandler          'if so, go handle it
  685.  
  686.  
  687.  
  688.     The equivalent code in PBFiles would be:
  689.  
  690.  
  691.         FileNum% = OpenF%(FileName$)     'an error might happen here
  692.            IF ErrorCode% THEN            'see if an error occured
  693.               CALL ErrorHandler          'if so, go handle it
  694.  
  695.  
  696.     It is important to realize that PBFiles won't handle errors for
  697.     you.  What PBFiles will do is trap the error and let you know
  698.     which error it was.  To handle errors actively, you must use an
  699.     error handler in your program.
  700.  
  701.     The writing of an error handler is not difficult to understand.
  702.     A typical error handler will consist of a SELECT CASE structure
  703.     in which the various errors you anticipate are grouped according
  704.     to the various messages you want to display or actions you want
  705.     your program to take.
  706.  
  707.  
  708.         SELECT CASE ErrorCode%
  709.            CASE 2
  710.               PRINT  "File not found."
  711.            CASE 3
  712.               PRINT  "Path not found."
  713.            CASE 4
  714.            .
  715.            .
  716.            CASE ELSE
  717.               PRINT  "Unknown error. Error code:"; ErrorCode%
  718.         END SELECT
  719.  
  720.  
  721.     At the very least, an error handler reports error codes along
  722.     with descriptive messages.  A more comprehensive error handler
  723.     will allow your program the chance to resolve the error, or to
  724.     shut down gracefully and save your data if possible.
  725.  
  726.  
  727.  
  728.  
  729.     DOS ERROR CODES
  730.  
  731.  
  732.     The following list of DOS error codes isn't exhaustive.  It
  733.     includes the most likely file access errors in a single-user,
  734.     non-networked environment.  Consult a DOS reference for a
  735.     complete listing of DOS errors.
  736.  
  737.     ErrorCode% may also report one non-standard error code: -1.
  738.     This error code is reported when GetLineF$ is unable to allocate
  739.     a string to use as an internal buffer.
  740.  
  741.  
  742.        2     File not found
  743.        3     Path not found
  744.        4     No file handles available
  745.        5     Access denied
  746.        6     Invalid handle
  747.        8     Insufficient memory
  748.        15    Invalid drive
  749.        19    Write-protected disk
  750.        21    Drive not ready
  751.        25    Seek error
  752.        26    Unknown media type
  753.        27    Disk sector not found
  754.        28    Out of paper (when writing to STDPRN)
  755.        29    Write fault
  756.        30    Read fault
  757.        31    General failure
  758.  
  759.  
  760.  
  761.  
  762.     ABOUT DOS STDXXX DEVICES
  763.  
  764.  
  765.     Each time your computer boots, DOS opens a set of 5 handles,
  766.     numbered 0-4.  These handles are assigned to 5 standard devices.
  767.     DOS uses these handles to access the devices for its own input
  768.     and output.  They are:
  769.  
  770.  
  771.        Device:      Handle:      Initialized as:
  772.        -------      -------      ---------------
  773.         STDIN          0            Keyboard
  774.         STDOUT         1             Screen
  775.         STDERR         2             Screen
  776.         STDAUX         3           Com port 1
  777.         STDPRN         4          Printer (LPT1)
  778.  
  779.  
  780.  
  781.     Because PBFiles is handle-based, you can take advantage of these
  782.     STDxxx devices by passing their handles to the various PBFiles
  783.     routines.
  784.  
  785.     You should realize that using these DOS devices can be a crude
  786.     method of input and output.  Only in a few situations will there
  787.     be any advantage to using them, and in many cases there will be
  788.     disadvantages.  Most especially, I do not recommend that you try
  789.     to use STDAUX and PBFiles as a substitute for the built-in
  790.     communications capabilities of PowerBASIC.
  791.  
  792.     Two examples come quickly to mind where a STDxxx device has an
  793.     advantage over using BASIC's own commands.  One is where you
  794.     want to direct your program's output through the ANSI.SYS device
  795.     driver.  The other is when you want to be able to redirect or
  796.     pipe input or output from the command line.
  797.  
  798.     To output a string to the screen through DOS services, you could
  799.     use BASIC code similar to this:
  800.  
  801.  
  802.        OPEN "CONS:" FOR OUTPUT AS #1
  803.        OutPut$ = "This will reach the screen via DOS."
  804.        PRINT #1, OutPut$
  805.  
  806.  
  807.     The PBFiles (rough) equivalent would be this:
  808.  
  809.  
  810.        %STDOUT = 1
  811.        OutPut$ = "This will reach the screen via DOS."
  812.        PutStF %STDOUT, OutPut$ + CHR$(13,10)
  813.  
  814.  
  815.     In this example, OutPut$ would be (normally) be written to the
  816.     screen by DOS.  If DOS redirection were in effect, the string
  817.     would be output to the device or file indicated on the command
  818.     line, instead of to the screen.  If OutPut$ included ANSI escape
  819.     codes, they could be intercepted and acted upon by ANSI.SYS.
  820.  
  821.     Most of the routines in PBFiles will accept STDxxx handles, with
  822.     two exceptions.  CloseF will not close a handle numbered 0-4,
  823.     and GetLineF$, because of its internal buffer and internal
  824.     pointer, cannot accept a DOS device handle, either.
  825.  
  826.     Overall, if you require DOS redirection in your programs, you
  827.     should be able to manage it, using just the routines in PBFiles.
  828.     But it may take some experimentation.  For more information
  829.     about DOS STDxxx devices, you should consult a good DOS
  830.     reference.
  831.  
  832.  
  833.  
  834.  
  835.     AVOIDING PROBLEMS WITH HUGE ARRAYS
  836.  
  837.  
  838.     Using the HUGE keyword lets you to dimension arrays that are
  839.     larger than a single 64K segment.  To accomplish this the
  840.     PowerBASIC compiler must know when the current array segment
  841.     contains all the elements it can hold, so it can skip ahead to
  842.     the first byte of the next 64K segment, where it locates the
  843.     next element.
  844.  
  845.     As an example, let's imagine you want to dimension an array of
  846.     1000 fixed length strings, where each string is 80 bytes long.
  847.     This makes an array 80000 bytes long.  Obviously this is greater
  848.     than one 64K segment, so it must be dimensioned as a HUGE array:
  849.  
  850.  
  851.         DIM HUGE FixedStrings(1 TO 1000) AS STRING * 80
  852.  
  853.  
  854.     The compiler can put 819 elements of 80 bytes each into the
  855.     first 64K segment.  At that point it has used up 65520 bytes of
  856.     the segment and it only has 16 bytes left in that segment.
  857.     That's not enough to hold a complete element, so the compiler
  858.     will insert 16 unused bytes into the array at that point.  This
  859.     permits element 820 to start at a new 64K segment boundary.
  860.  
  861.     In the BASIC environment, placing a discontinuity like this into
  862.     the data in HUGE arrays is not a problem, because array elements
  863.     are always accessed individually in BASIC.  PBFiles, however,
  864.     has two routines that allow you to access entire arrays or
  865.     portions of arrays all at once, GetF and PutF.
  866.  
  867.     The difficulty arises because these commands read data as a
  868.     continuous series of bytes, while the compiler may be storing
  869.     the data in a discontinuous series of bytes.  In our example
  870.     array, a discontinuity of 16 bytes occurs between elements 819
  871.     and 820.
  872.  
  873.     Now let's say you want to save a copy of this HUGE array into a
  874.     file, using PutF.  It might seem natural to write code like
  875.     this:
  876.  
  877.  
  878.         FileName$ = "FIXSTRNG.DAT"
  879.         SaveHandle% = OpenF%(FileName$) ' open a file to save into
  880.  
  881.         Bytes& = CLNG(80 * 1000)        ' calculate bytes to save
  882.         PutF SaveHandle%, Bytes&, FixedStrings(1)      'save them
  883.  
  884.  
  885.     The problem comes in the third line, in calculating how many
  886.     bytes we need to write into the file.  Yes, there are 80000
  887.     bytes of data to be read, but because of the 16 unused bytes
  888.     that were inserted at the end of the first 64K segment, those
  889.     80000 bytes of data are stored across 80016 bytes of memory!
  890.  
  891.     The example code shown above will not work, because PutF is not
  892.     smart enough to skip over the 16 bytes of non-data inserted into
  893.     the array.  Instead it will read those 16 bytes of padding into
  894.     the file and it will stop before it reads the final 16 bytes of
  895.     data.
  896.  
  897.     The easy way to work around this problem is to read each element
  898.     individually, in a loop, and write each one to the file:
  899.  
  900.  
  901.         FileName$ = "FIXSTRNG.DAT"
  902.         SaveHandle% = OpenF%(FileName$) ' open a file to save into
  903.  
  904.         Bytes& = 80&                    ' read one element at a time
  905.         FOR X% = 1 TO 1000
  906.           PutF SaveHandle%, Bytes&, FixedStrings(X%)
  907.         NEXT X%
  908.  
  909.  
  910.     This code works because the correct address of each element will
  911.     be passed to PutF and the 16 bytes of padding after element 819
  912.     will be skipped over, automatically.  PowerBASIC will pass the
  913.     correct address for element 819, then the correct address for
  914.     element 820.
  915.  
  916.     This is not the fastest solution possible, but it is by far the
  917.     simplest.  It is not the fastest because it requires your
  918.     program to access the disk 1000 times, instead of once.
  919.  
  920.     Another possible work around is to make the disk file 80016
  921.     bytes long, so it contains all the data, along with the gap in
  922.     the data.  Then you could load the resulting file directly into
  923.     a HUGE array having the same dimensions as the original array,
  924.     using GetF, because an identical array will have the same gap in
  925.     the data, located in the same place.
  926.  
  927.     This last approach is fairly simple and and also the fastest,
  928.     since it uses the fewest disk reads or writes.  However, it is
  929.     also the least flexible approach, since it requires you to load
  930.     the file into an array that is identically dimensioned to the
  931.     original array.
  932.  
  933.     Remember, this problem only applies to HUGE arrays where the
  934.     element size is not a power of two.  The only PowerBASIC arrays
  935.     that might fit that description would be arrays of TYPE
  936.     variables, or fixed-length strings, or extended precision
  937.     numbers or BCD floating point numbers.  The first two of those
  938.     variable types can have almost any length.  The last two have a
  939.     fixed length of 10 bytes each.
  940.  
  941.  
  942.     **************************************************************
  943.  
  944.  
  945.  
  946.  
  947.     PBFILES REFERENCE
  948.  
  949.  
  950.  
  951.     The following is a list of PBFiles routines along with their
  952.     closest counterparts in PowerBASIC:
  953.  
  954.  
  955.        OpenF% ................ OPEN (...FOR BINARY)
  956.        SetAccessCode ......... ACCESS LOCK/UNLOCK/READ/WRITE, etc.
  957.        CloseF ................ CLOSE# (close one open file)
  958.        PutF .................. PUT    (file statement)
  959.        GetF .................. GET    (file statement)
  960.        PutStF ................ PUT$
  961.        GetStF ................ GET$
  962.        SaveF ................. BSAVE
  963.        LoadF ................. BLOAD
  964.        GetLineF$ ............. LINE INPUT# (file statement)
  965.        EndF% ................. EOF
  966.        GetLocF& .............. SEEK   (as a function)
  967.        SetLocF ............... SEEK   (as a statement)
  968.        SizeF& ................ LOF
  969.        KillF ................. KILL
  970.        FlushF ................ FLUSH
  971.        ErrorCode% ............ ERR
  972.        SetErrorCode .......... ERROR
  973.        SetPtrBase ............ OPTION BASE
  974.  
  975.  
  976.     PBFiles also includes the following commands that have no exact
  977.     equivalent in BASIC:
  978.  
  979.  
  980.        ClipF ................. truncates a file
  981.        GetPtrBase% ........... returns value set by SetPtrBase
  982.        HandleF% .............. returns latest handle opened
  983.        SaveLineF ............. allows GetLineF to read multiple files
  984.        SetBufferSize ......... controls size of buffer for GetLineF
  985.  
  986.  
  987.     NOTE: Although the routines in PBFiles include some support for
  988.     networks, they have not been tested in a networked environment.
  989.     If you intend to use PBFiles on a network, you should test your
  990.     code thoroughly to ensure it is network safe.
  991.  
  992.  
  993.  
  994.  
  995.  
  996.     ClipF
  997.     -----------------------------------------------------------------
  998.  
  999.     DECLARE SUB ClipF (Handle%, NewSize&)
  1000.  
  1001.     Parameters: Handle% = handle of file to truncate
  1002.                 NewSize& = new size of file, in bytes, as long integer
  1003.  
  1004.  
  1005.  
  1006.     ClipF lets you truncate an opened file to the size you specify:
  1007.  
  1008.  
  1009.        ClipF Handle%, 3500&
  1010.  
  1011.  
  1012.     The above code shortens the file designated by Handle% to a
  1013.     length of 3500 bytes, assuming the file was more than 3500 bytes
  1014.     long.
  1015.  
  1016.     After a call to ClipF the file pointer will point to the first
  1017.     byte immediately following the new end byte of the file.  In the
  1018.     example above (assuming a zero-based convention for counting
  1019.     bytes), the first byte of the file would be byte zero, the final
  1020.     byte of the file would be byte 3499 and the pointer would be at
  1021.     byte 3500.
  1022.  
  1023.     IMPORTANT: If NewSize& exceeds the current file size then ClipF
  1024.     will move the pointer one byte beyond the current end byte of
  1025.     the file, but the file will remain the same size.
  1026.  
  1027.     For more information about file pointers, see ABOUT FILE
  1028.     POINTERS.
  1029.  
  1030.     See also SetLocF.
  1031.  
  1032.  
  1033.  
  1034.  
  1035.     CloseF
  1036.     -----------------------------------------------------------------
  1037.  
  1038.     DECLARE SUB CloseF (Handle%)
  1039.  
  1040.     Parameters: Handle% = handle of file to close
  1041.  
  1042.  
  1043.  
  1044.     CloseF is a substitute for CLOSE #FileNum in BASIC.  It closes
  1045.     one file opened by OpenF%.
  1046.  
  1047.  
  1048.        CloseF Handle%
  1049.  
  1050.  
  1051.     The above code closes the file designated by Handle%.  CloseF
  1052.     will ignore any attempts to close a handle numbered 0-4.  Those
  1053.     handles are reserved by DOS and closing them would be a mistake.
  1054.  
  1055.  
  1056.  
  1057.  
  1058.     EndF
  1059.     -----------------------------------------------------------------
  1060.  
  1061.     DECLARE FUNCTION EndF% ()
  1062.  
  1063.     Parameters: none
  1064.  
  1065.  
  1066.     EndF% is a substitute for EOF.  It works in conjunction with
  1067.     GetLineF$ only.  While GetLineF$ is processing a text file and
  1068.     bytes remain to be read, EndF% returns a zero.  When GetLineF$
  1069.     reaches the end of the file and no more bytes remain to be read,
  1070.     EndF% returns -1.
  1071.  
  1072.  
  1073.        DO
  1074.          X% = X% + 1
  1075.          Array$(X%) = GetLineF$(Handle%)
  1076.        LOOP UNTIL EndF% OR ErrorCode%
  1077.  
  1078.  
  1079.     The above code loads a variable length string array with lines
  1080.     of text from the file designated by Handle%.  The loop will
  1081.     iterate until the end of the file is reached, or an error
  1082.     occurs.
  1083.  
  1084.     EndF% will not report the end of a file when a CHR$(26) is
  1085.     encountered in a file.
  1086.  
  1087.     See also GetLineF$.
  1088.  
  1089.  
  1090.  
  1091.  
  1092.     ErrorCode
  1093.     -----------------------------------------------------------------
  1094.  
  1095.     DECLARE FUNCTION ErrorCode% ()
  1096.  
  1097.     Parameters: none
  1098.  
  1099.  
  1100.     When an error occurs during any of the PBFiles routines, the
  1101.     error is trapped (no action is taken by DOS or BASIC) and the
  1102.     error code is stored in an internal variable.  This includes
  1103.     critical errors.  The current content of that variable is
  1104.     returned by ErrorCode%.
  1105.  
  1106.  
  1107.        IF ErrorCode% = 2 THEN PRINT "File not found!"
  1108.  
  1109.  
  1110.     For more information see HANDLING ERRORS and the section DOS
  1111.     ERROR CODES.
  1112.  
  1113.     See also SetErrorCode.
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.     FlushF
  1120.     -----------------------------------------------------------------
  1121.  
  1122.     DECLARE SUB FlushF (Handle%)
  1123.  
  1124.     Parameters: Handle% = handle of the file to flush to disk
  1125.  
  1126.  
  1127.  
  1128.     FlushF is a substitute for FLUSH.  FlushF causes the contents of
  1129.     the file buffers (maintained by DOS) to be written to disk.
  1130.     Files that have been flushed remain open.
  1131.  
  1132.  
  1133.         FlushF Handle%
  1134.  
  1135.  
  1136.     The above code flushes the complete contents of the file
  1137.     designated by Handle% onto disk.
  1138.  
  1139.     Flushing is important if you are working with highly valuable
  1140.     data, because any data that is not fully written to disk is
  1141.     vulnerable to loss if something disrupts the operation of the
  1142.     computer running your program.
  1143.  
  1144.     See also CloseF.
  1145.  
  1146.  
  1147.  
  1148.  
  1149.     GetF
  1150.     -----------------------------------------------------------------
  1151.  
  1152.     DECLARE SUB GetF (Handle%, Bytes&, ToVariable AS ANY)
  1153.  
  1154.     Parameters: Handle% = the handle of the file to read from
  1155.                 Bytes& = number of bytes to read
  1156.                 ToVariable = the variable to read the data into
  1157.  
  1158.  
  1159.  
  1160.     GetF resembles GET, but is more powerful.  It allows you to read
  1161.     Bytes& number of bytes from a file into a variable or into an
  1162.     array.  You must specify the handle of the file to read from,
  1163.     the number of bytes to read, and the variable to read into.  If
  1164.     you are reading into an array, you need to specify the first
  1165.     element of the range to be read into:
  1166.  
  1167.  
  1168.        GetF Handle%, 4000&, Arry&(100)
  1169.  
  1170.  
  1171.     The above example reads 4000 bytes from the file specified by
  1172.     Handle% into Arry&() starting at element 100.
  1173.  
  1174.     IMPORTANT: Before using GetF with HUGE arrays, read the section
  1175.     AVOIDING PROBLEMS WITH HUGE ARRAYS.
  1176.  
  1177.     GetF always reads from the file starting at the position of the
  1178.     file pointer.  GetF will automatically advance the file pointer
  1179.     one byte forward for each byte it reads.  It is up to you to
  1180.     make certain the file pointer is where you want it to be before
  1181.     calling GetF.
  1182.  
  1183.     If you tell GetF to write more bytes than the target variable or
  1184.     array can hold, it will overwrite whatever lies beyond the end
  1185.     of your variable or array.  If you tell it to write too few
  1186.     bytes, whatever "garbage" was in that area of RAM won't be fully
  1187.     overwritten.  It is your responsibility to calculate the correct
  1188.     number of bytes.
  1189.  
  1190.     If you try to read from a file when the file pointer is located
  1191.     beyond its end, then GetF will simply return with no action
  1192.     taken and no error code.  If you try to read more bytes than are
  1193.     available between the pointer and the end byte of the file, GetF
  1194.     will read as far as the end byte of the file and stop.
  1195.  
  1196.     If Bytes& is less than or equal to zero, GetF will return
  1197.     without taking any action.  No error will be reported.
  1198.  
  1199.     NOTE: When a parameter is declared AS ANY it must be passed as a
  1200.     variable.  If you pass an equation, constant or literal value,
  1201.     the compiler will report Error 426: Variable expected.
  1202.  
  1203.     GetF can write to both variables or arrays of the following
  1204.     types: fixed-length strings, numeric variables, and TYPE
  1205.     variables.
  1206.  
  1207.     GetF is NOT suitable for reading from files into variable length
  1208.     strings, flex strings or arrays of such strings.  For these
  1209.     strings you would use GetStF or GetLineF$.
  1210.  
  1211.     See also PutF.
  1212.  
  1213.  
  1214.  
  1215.  
  1216.     GetLineF
  1217.     -----------------------------------------------------------------
  1218.  
  1219.     DECLARE FUNCTION GetLineF$ (Handle%)
  1220.  
  1221.     Parameters: Handle% = the handle of the file to read from
  1222.  
  1223.  
  1224.  
  1225.     GetLineF$ is a substitute for LINE INPUT#.  It simplifies the
  1226.     task of reading ASCII text files one line at time.
  1227.  
  1228.  
  1229.        TextLine$ = GetLineF$(Handle%)
  1230.  
  1231.  
  1232.     The above code returns one line of text from the file designated
  1233.     by Handle%.  The line of text starts with the character at the
  1234.     current file pointer and includes all characters up to but not
  1235.     including the first carriage return character, or CHR$(13).  If
  1236.     the first character encountered is a CHR$(13), GetLineF$ returns
  1237.     a null string.
  1238.  
  1239.     The longest string GetLineF$ may return is 256 bytes.  When
  1240.     GetLineF$ does not encounter a CHR$(13) within the first 256
  1241.     characters it simply returns those 256 characters.
  1242.  
  1243.     GetLineF$ allocates a string to use as an internal buffer.  The
  1244.     default size of this buffer is 8174 bytes.  When GetLineF$
  1245.     detects the end of a file, it sets the value reported by EndF%
  1246.     to -1 and it deallocates its buffer.
  1247.  
  1248.     If GetLineF$ fails to allocate a string to use as a buffer, it
  1249.     will return a non-standard error code of -1.  One common way for
  1250.     the buffer allocation to fail is if your code uses the
  1251.     metacommand $STRING to set a string segment size smaller than
  1252.     8K.  The default buffer size of 8174 bytes requires an 8K string
  1253.     segment (or larger).
  1254.  
  1255.     If buffer allocation fails, or if you require a larger or
  1256.     smaller buffer for other reasons, you may change the size of the
  1257.     buffer.  See SetBufferSize for more details.
  1258.  
  1259.     Buffering requires GetLineF$ to maintain its own internal
  1260.     pointer, which will rarely agree with the "regular" file
  1261.     pointer.  For that reason, if you use GetLineF$ to read from
  1262.     more than one file at once, you may need to use SaveLineF.  For
  1263.     more details, see SaveLineF.
  1264.  
  1265.     GetLineF$ will not accept a handle for a DOS STDxx device (0-4).
  1266.     If you call GetLineF$ with such a handle, it will simply return
  1267.     a null string and report an "invalid handle" error (6).
  1268.  
  1269.     See also EndF%, GetStF.
  1270.  
  1271.  
  1272.  
  1273.  
  1274.     GetLocF
  1275.     -----------------------------------------------------------------
  1276.  
  1277.     DECLARE FUNCTION GetLocF& (Handle%)
  1278.  
  1279.     Parameters: Handle% = handle of file in which to find pointer
  1280.  
  1281.  
  1282.  
  1283.     GetLocF& is a substitute for the function form of SEEK.  It
  1284.     returns a long integer representing the present position of the
  1285.     file pointer within the file specified by Handle%:
  1286.  
  1287.  
  1288.        PtrLoc& = GetLocF&(Handle%)
  1289.  
  1290.  
  1291.     The above code returns the current position of the file pointer
  1292.     in the file designated by Handle%.
  1293.  
  1294.     By default, the file is assumed to start at byte 0 (zero).  This
  1295.     default may be changed to start at byte 1 by using the command
  1296.     SetPtrBase.  See SetPtrBase or GetPtrBase for further details.
  1297.  
  1298.     If an error occurs during a call to GetLocF&, it returns a zero.
  1299.     Normally, zero is a legal file pointer location.  To determine
  1300.     with certainty whether an error has occured you must call
  1301.     ErrorCode%.
  1302.  
  1303.     See also SetLocF.
  1304.  
  1305.  
  1306.  
  1307.  
  1308.     GetPtrBase
  1309.     -----------------------------------------------------------------
  1310.  
  1311.     DECLARE FUNCTION GetPtrBase% ()
  1312.  
  1313.     Parameters: none
  1314.  
  1315.  
  1316.  
  1317.     GetPtrBase% returns the base value used by GetLocF& and SetLocF:
  1318.  
  1319.  
  1320.        Base% = GetPtrBase%
  1321.  
  1322.  
  1323.     The above code returns the current pointer base value.  The
  1324.     default value is zero, but you may change the value to 1, by
  1325.     calling SetPtrBase.
  1326.  
  1327.     Normally, DOS defines the first byte of a file as byte 0 (zero).
  1328.     However, when Microsoft introduced BINARY file handling into
  1329.     BASIC, it chose to treat the first byte of a file as byte 1. To
  1330.     accomodate code written for this convention, PBFiles includes
  1331.     the commands SetPtrBase and GetPtrBase%.
  1332.  
  1333.     When GetPtrBase% returns zero, PBFiles is acting under the
  1334.     zero-based (DOS) convention.  Under this convention, when the
  1335.     pointer is at the second byte of a file, GetLocF& will return 1,
  1336.     and if you want to set the pointer to the second byte you would
  1337.     use SetLocF 1.
  1338.  
  1339.     When GetPtrBase% returns 1, PBFiles is acting under the
  1340.     one-based (Microsoft BASIC) convention.  Under this convention,
  1341.     when the pointer is at the second byte of a file, GetLocF& will
  1342.     return 2, and to set the pointer to the second byte you would
  1343.     use SetLocF 2.
  1344.  
  1345.     See also SetPtrBase.
  1346.  
  1347.  
  1348.  
  1349.  
  1350.     GetStF
  1351.     -----------------------------------------------------------------
  1352.  
  1353.     DECLARE SUB GetStF (Handle%, ToString AS ANY)
  1354.  
  1355.     Parameters: Handle% = handle of the file to read from
  1356.                 ToString = variable or flex string to read data into
  1357.  
  1358.  
  1359.  
  1360.     GetStF is a substitute for GET$.  It lets you read from a file
  1361.     into a variable length string or flex string.  Before calling
  1362.     GetStF the string must be initialized to the length you want.
  1363.     The length of the string determines the number of bytes GetStF
  1364.     will read from the file into the string:
  1365.  
  1366.  
  1367.        Target$ = SPACE$(100) 
  1368.        GetStF Handle%, Target$
  1369.  
  1370.  
  1371.     In the above code, 100 bytes would be read from the file
  1372.     specified by Handle% into Target$.  The file would be read
  1373.     beginning at the current position of the file pointer.  GetStF
  1374.     will advance the file pointer one byte for each byte read.
  1375.  
  1376.     If you try to read from a file when the file pointer is located
  1377.     beyond its end, then GetStF will simply return with no action
  1378.     taken and no error code.  If you try to read more bytes than are
  1379.     available between the pointer and the end byte of the file,
  1380.     GetStF will read as far as the end byte of the file and stop.
  1381.  
  1382.     NOTE: When a parameter is declared AS ANY it must be passed as a
  1383.     variable.  If you pass an equation, constant or literal value,
  1384.     the compiler will report Error 426: Variable expected.
  1385.  
  1386.     If you want your program to read an ASCII text file (one which
  1387.     uses a carriage return and linefeed to delimit each line of
  1388.     text) you will probably want to use GetLineF$, rather than
  1389.     GetStF.
  1390.  
  1391.     See also PutStF.
  1392.  
  1393.  
  1394.  
  1395.  
  1396.     HandleF
  1397.     -----------------------------------------------------------------
  1398.  
  1399.     DECLARE FUNCTION HandleF% ()
  1400.  
  1401.     Parameters: none
  1402.  
  1403.  
  1404.     HandleF% returns the handle of the file most recently opened by
  1405.     OpenF%.  Among other things it allows you to use the following
  1406.     alternate logic when opening a file:
  1407.  
  1408.  
  1409.        IF OpenF%(FileSpec$) THEN
  1410.           Handle% = HandleF%      'get the handle for FileSpec$
  1411.        ELSE
  1412.           Call ErrorHandler
  1413.        END IF
  1414.  
  1415.  
  1416.     It is not recommended that you use HandleF% as a substitute for
  1417.     a file handle variable.
  1418.  
  1419.     See also OpenF.
  1420.  
  1421.  
  1422.  
  1423.  
  1424.     KillF
  1425.     -----------------------------------------------------------------
  1426.  
  1427.     DECLARE SUB KillF (FileSpec$)
  1428.  
  1429.     Parameters: FileSpec$ = name of the file to kill (delete)
  1430.  
  1431.  
  1432.  
  1433.     KillF is a substitute for KILL.  It accepts a file name, which
  1434.     may be up to 64 characters long and include a drive and
  1435.     subdirectory path, but not wildcard characters:
  1436.  
  1437.  
  1438.        FileName$ = "D:\PATH\FILENAME.EXT"   'no wildcards
  1439.        KillF FileName$                      'delete the file
  1440.  
  1441.  
  1442.     Do not try to kill a file when it is open.  Close it first using
  1443.     CloseF.  If you kill a file when it is open PBFiles will not
  1444.     report an error, but you may end up with a mess, possibly
  1445.     including cross-linked files that must be repaired by the DOS
  1446.     CHKDSK command.
  1447.  
  1448.  
  1449.  
  1450.  
  1451.     LoadF
  1452.     -----------------------------------------------------------------
  1453.  
  1454.     DECLARE SUB LoadF (Handle%, Bytes&, ToSegment??)
  1455.  
  1456.     Parameters: Handle% = handle of the file to load data from
  1457.                 Bytes& = number of bytes to load
  1458.                 ToSegment?? = segment at which to load the data
  1459.  
  1460.  
  1461.  
  1462.     LoadF resembles BLOAD, but is more powerful.  Before you can
  1463.     load a file with LoadF you must open it using OpenF%.  You pass
  1464.     LoadF the handle of an opened file, the number of bytes to load,
  1465.     and the segment address where you want them loaded.  It assumes
  1466.     an offset of zero.
  1467.  
  1468.  
  1469.        LoadF Handle%, 4000&, &HB800
  1470.  
  1471.  
  1472.     The above code loads 4000 bytes from the file designated by
  1473.     Handle% starting at the address &HB800:0000 (page zero of a
  1474.     color monitor's video RAM, in text mode).
  1475.  
  1476.     You may set the file pointer wherever you wish before calling
  1477.     LoadF, and therefore may read from the file at any point.  This
  1478.     allows you to have more than one screen saved in a single file.
  1479.  
  1480.     If you try to read from the file when the pointer is located
  1481.     beyond its end, then LoadF will simply return with no action
  1482.     taken and no error code.  If you try to read more bytes than are
  1483.     available between the pointer and the end byte of the file,
  1484.     LoadF will read as far as the end byte of the file and stop.
  1485.  
  1486.     If Bytes& is less than or equal to zero, LoadF will return
  1487.     without taking any action.  No error will be reported.
  1488.  
  1489.     Unlike BLOAD, LoadF will not close the file for you.  You must
  1490.     close it using CloseF.
  1491.  
  1492.     See also SaveF.
  1493.  
  1494.  
  1495.  
  1496.  
  1497.     OpenF
  1498.     -----------------------------------------------------------------
  1499.  
  1500.     DECLARE FUNCTION OpenF% (FileSpec$)
  1501.  
  1502.     Parameters: FileSpec$ = name of the file to open or create
  1503.  
  1504.  
  1505.  
  1506.     OpenF% is a substitute for OPEN FOR BINARY.  It accepts a
  1507.     FileName$ up to 64 characters long, which can include a drive
  1508.     and path, but not wildcard characters.  OpenF% opens the file
  1509.     named and returns the handle that you must use to access that
  1510.     file, or a zero if there was an error:
  1511.  
  1512.  
  1513.        FileName$ = "D:\PATH\FILENAME.EXT"   'no wildcards allowed
  1514.        Handle% = OpenF%(FileName$)
  1515.  
  1516.  
  1517.     When OpenF% opens a file, it sets the file access code according
  1518.     to an internal variable.  This variable defaults to the code for
  1519.     read-write access and network compatibility mode, but it may be
  1520.     changed by making a call to SetAccessCode.
  1521.  
  1522.     If OpenF% can't find FileName$, it creates a zero-length, normal
  1523.     attribute file of that name.  Created files are opened using the
  1524.     current access code.  This requires OpenF% to create the file
  1525.     first without the access code, close it and then immediately
  1526.     reopen it using the access code.  An access code is not the same
  1527.     as a file attribute.
  1528.  
  1529.     When a file is first opened the file pointer always points to
  1530.     the first byte of the file.  Normally, the first byte is
  1531.     considered to be byte 0 (zero).  PBFiles also lets you regard
  1532.     this byte as byte 1. For more information, see SetPtrBase and
  1533.     GetPtrBase%.
  1534.  
  1535.     If an error occurs during a call to OpenF%, it returns a zero
  1536.     rather than a file handle.  Zero is a valid handle, but it is
  1537.     reserved by DOS for STDIN.  If OpenF% returns a zero, don't use
  1538.     it!  Instead, call ErrorCode%.
  1539.  
  1540.     When FileName$ is null or more than 64 characters, then OpenF%
  1541.     treats these conditions as "file not found" errors.
  1542.  
  1543.     If FileName$ includes wildcard characters (?*) then your program
  1544.     will crash!  Your program must trap this error before calling
  1545.     OpenF%.
  1546.  
  1547.     See also CloseF.
  1548.  
  1549.  
  1550.  
  1551.  
  1552.     PutF
  1553.     -----------------------------------------------------------------
  1554.  
  1555.     DECLARE SUB PutF (Handle%, Bytes&, FromVariable AS ANY)
  1556.  
  1557.     Parameters: Handle% = the handle of the file to write to
  1558.                 Bytes& = number of bytes to write
  1559.                 FromVariable = the variable to write the data from
  1560.  
  1561.  
  1562.  
  1563.     PutF resembles PUT, but is more powerful.  It allows you to
  1564.     write Bytes& number of bytes from a variable or an array to a
  1565.     disk file.  You pass PutF the handle of the file to write to,
  1566.     the number of bytes to write and the variable to be written
  1567.     from.  If you are writing from an array, pass PutF the first
  1568.     element of the range to be written from:
  1569.  
  1570.  
  1571.        PutF Handle%, 4000&, Arry&(100)
  1572.  
  1573.  
  1574.     The above code writes 4000 bytes from Arry&(), starting at
  1575.     element 100, into the file specified by Handle%.  PutF will
  1576.     write to the file starting at the location of the file pointer.
  1577.     The file pointer will advance one byte for each byte written.
  1578.  
  1579.     IMPORTANT: Before using PutF with HUGE arrays, read the section
  1580.     AVOIDING PROBLEMS WITH HUGE ARRAYS.
  1581.  
  1582.     If the file pointer is anywhere but the end of the file, the
  1583.     previous contents of the file will be overwritten as PutF writes
  1584.     the new bytes to those locations.  It is up to you to make
  1585.     certain the file pointer is pointing where you want it, before
  1586.     calling PutF.
  1587.  
  1588.     PutF will ignore any attempt to write zero bytes.  This is
  1589.     because writing zero bytes has the (sometimes traumatic) effect
  1590.     of truncating a disk file.  If you desire this effect, see
  1591.     ClipF.
  1592.  
  1593.     If Bytes& is less than or equal to zero, PutF will return
  1594.     without taking any action.  No error will be reported.
  1595.  
  1596.     NOTE: When a parameter is declared AS ANY it must be passed as a
  1597.     variable.  If you pass an equation, constant or literal value,
  1598.     the compiler will report Error 426: Variable expected.
  1599.  
  1600.     PutF can write variables or arrays of the following types:
  1601.     fixed-length strings, numeric variables or TYPE variables.
  1602.  
  1603.     PutF is NOT suitable for use with variable length strings, flex
  1604.     strings, or arrays of such strings.  Instead, see PutStF.
  1605.  
  1606.     See also GetF.
  1607.  
  1608.  
  1609.  
  1610.  
  1611.  
  1612.     PutStF
  1613.     -----------------------------------------------------------------
  1614.  
  1615.     DECLARE SUB PutStF (Handle%, FromString AS ANY)
  1616.  
  1617.     Parameters: Handle% = handle of the file to write to
  1618.                 FromString = string to write data from
  1619.  
  1620.  
  1621.  
  1622.     PutStF is a substitute for PUT$.  It allows you to write a
  1623.     variable length string or flex string to a file:
  1624.  
  1625.  
  1626.        St$ = "This is a test."
  1627.        PutStF Handle%, St$
  1628.  
  1629.  
  1630.     The above code writes St$ to the file designated by Handle%.
  1631.     The string will be written starting at the current position of
  1632.     the file pointer.  PutStF will advance the file pointer one byte
  1633.     for each byte written.
  1634.  
  1635.     If the file pointer is anywhere but the end of the file, the
  1636.     previous contents of the file will be overwritten as PutStF
  1637.     writes the new bytes to those locations.  It is up to you to
  1638.     make certain the file pointer is pointing where you want it,
  1639.     before calling PutStF.
  1640.  
  1641.     NOTE: When a parameter is declared AS ANY it must be passed as a
  1642.     variable.  If you pass an equation, constant or literal value,
  1643.     the compiler will report Error 426: Variable expected.
  1644.  
  1645.     See also GetStF.
  1646.  
  1647.  
  1648.  
  1649.  
  1650.     SaveF
  1651.     -----------------------------------------------------------------
  1652.  
  1653.     DECLARE SUB SaveF (Handle%, Bytes&, FromSegment??)
  1654.  
  1655.     Parameters: Handle% = handle of the file to write to
  1656.                 Bytes& = number of bytes to write
  1657.                 FromSegment?? = segment to save data from
  1658.  
  1659.  
  1660.  
  1661.     SaveF resembles BSAVE, but is more powerful.  It allows you to
  1662.     read from a memory location, such as video memory, directly into
  1663.     a file.  Notice that SaveF only lets you to pass the segment
  1664.     portion of the address from which you want data saved.  It
  1665.     assumes an offset of zero.
  1666.  
  1667.  
  1668.        SaveF Handle%, 4000&, &HB800
  1669.  
  1670.  
  1671.     In the above code, the 4000 bytes starting at &HB800:0000 (page
  1672.     zero of a color monitor's video RAM in text mode) will be
  1673.     written to the file designated by Handle%, starting at the
  1674.     current position of the file pointer.
  1675.  
  1676.     Before you can save to a file using SaveF, you must open the
  1677.     file using OpenF%.  Also, SaveF will not close the file for you.
  1678.     You must close the file seperately, using CloseF, when you are
  1679.     done with it.
  1680.  
  1681.     You may use SaveF to write more than 64K bytes at once.  Also,
  1682.     you may append data onto the end of an existing file, so you may
  1683.     have as many screens full of information as you wish in a single
  1684.     file.
  1685.  
  1686.     If Bytes& is less than or equal to zero, SaveF will return
  1687.     without taking any action.  No error will be reported.
  1688.  
  1689.     SaveF does NOT add a header to your files, as BSAVE does.
  1690.  
  1691.     See also LoadF.
  1692.  
  1693.  
  1694.  
  1695.  
  1696.     SaveLineF
  1697.     -----------------------------------------------------------------
  1698.  
  1699.     DECLARE SUB SaveLineF ()
  1700.  
  1701.     Parameters: none
  1702.  
  1703.  
  1704.  
  1705.     SaveLineF resets the DOS file pointer of the file most recently
  1706.     read by GetLineF$ to match the internal file pointer maintained
  1707.     by GetLineF$.  SaveLineF is only needed under the following
  1708.     conditions:
  1709.  
  1710.       1) GetLineF$ has not finished reading file A to the end, and
  1711.       2) you must use GetLineF$ to read from a second file B, and
  1712.       3) you must return later to file A at the point you left off.
  1713.  
  1714.     Whenever these three conditions exist, you must call SaveLineF
  1715.     after your latest read from file A and before reading from file
  1716.     B, as in the following example:
  1717.  
  1718.  
  1719.        DO
  1720.           INCR LineCount%
  1721.  
  1722.           LineA$ = GetLineF$(A%)
  1723.             SaveLineF
  1724.             EndA% = EndF%
  1725.           LineB$ = GetLineF$(B%)
  1726.             SaveLineF
  1727.             EndB% = EndF%
  1728.  
  1729.           IF LineA$ <> LineB$ THEN
  1730.             PRINT "Lines"; LineCount%; " in A and B don't match."
  1731.           END IF
  1732.  
  1733.        LOOP UNTIL EndA% OR EndB%
  1734.  
  1735.  
  1736.     SaveLineF always resets the pointer of the file whose handle was
  1737.     last passed to GetLineF$.  If you call SaveLineF prior to your
  1738.     first call to GetLineF$, it will cause an "invalid handle"
  1739.     error.  If you have closed the file most recently read by
  1740.     GetLineF$, you will also get the same error.
  1741.  
  1742.     NOTE: Alternating line-by-line between files, as in the example
  1743.     above, causes GetLineF$ to repeatedly empty and refill its
  1744.     buffer, causing it to slow down significantly.  It would be much
  1745.     faster to use GetLineF$ to read each file into its own array and
  1746.     then to compare the lines afterward.
  1747.  
  1748.     See also GetLineF.
  1749.  
  1750.  
  1751.  
  1752.  
  1753.  
  1754.     SetAccessCode
  1755.     -----------------------------------------------------------------
  1756.  
  1757.     DECLARE SUB SetAccessCode (AccessCode%)
  1758.  
  1759.     Parameters: AccessCode% = access code to use in opening files
  1760.  
  1761.  
  1762.  
  1763.     SetAccessCode sets the file access code used by OpenF% when
  1764.     opening files:
  1765.  
  1766.  
  1767.        SetAccessCode 0
  1768.        Handle% = OpenF%(FileName$)
  1769.  
  1770.  
  1771.     The above code opens FileName$ with a read-only access code.
  1772.     This is not the same as giving the file a read-only attribute.
  1773.     When you set a new access code using SetAccessCode, all
  1774.     subsequent calls to OpenF% will use the new access code.
  1775.  
  1776.     These BASIC commands are equivalent to the following access
  1777.     codes:
  1778.  
  1779.  
  1780.        ACCESS READ WRITE  ...  2
  1781.        ACCESS READ    .......  0
  1782.        ACCESS WRITE   .......  1
  1783.        ACCESS READ SHARED ...  64
  1784.        LOCK READ      .......  50
  1785.        LOCK WRITE     .......  34
  1786.  
  1787.  
  1788.     IMPORTANT: PBFiles has not been tested in a networked
  1789.     environment.  If you use PBFiles in a network, you should test
  1790.     it until you are satisfied it is safe.
  1791.  
  1792.     For more complete information about access codes, consult a DOS
  1793.     reference.
  1794.  
  1795.  
  1796.  
  1797.  
  1798.     SetBufferSize
  1799.     -----------------------------------------------------------------
  1800.  
  1801.     DECLARE SUB SetBufferSize (Bytes%)
  1802.  
  1803.     Parameters: Bytes% = number of bytes to use for buffer
  1804.  
  1805.  
  1806.  
  1807.     SetBufferSize lets you change the size of the buffer allocated
  1808.     by GetLineF$.  The default buffer size is 8174 bytes.
  1809.  
  1810.  
  1811.        SetBufferSize 5000
  1812.  
  1813.  
  1814.     The example above sets the buffer size to 5000 bytes.
  1815.  
  1816.     If you try to set the buffer size above 32750 bytes or below
  1817.     1006 bytes, SetBufferSize will round the buffer size up or down
  1818.     to match the nearest of these limits.
  1819.  
  1820.     Because the buffer allocated by GetLineF$ is a string, it is
  1821.     affected by the string segment size set by $STRING.  The largest
  1822.     string that can be allocated within a string segment is the size
  1823.     of the segment minus 18 bytes.
  1824.  
  1825.     For example, if the example code above were preceeded by the
  1826.     metacommand $STRING 4, the buffer of 5000 bytes would not fit
  1827.     inside the 4K string segment, causing GetLineF$ to fail.  You
  1828.     would need to set the buffer size to between 4078 and 1006 bytes
  1829.     before your first call to GetLineF$ to compensate for the
  1830.     $STRING 4 statement.
  1831.  
  1832.     When GetLineF$ fails to allocate a buffer string, it returns the
  1833.     non-standard error code -1.
  1834.  
  1835.     See also GetLineF.
  1836.  
  1837.  
  1838.  
  1839.  
  1840.     SetErrorCode
  1841.     -----------------------------------------------------------------
  1842.  
  1843.     DECLARE SUB SetErrorCode (ErrorCode%)
  1844.  
  1845.     Parameters: ErrorCode% = value to place into internal error code
  1846.  
  1847.  
  1848.  
  1849.     SetErrorCode allows you to reset the error code reported by
  1850.     ErrorCode% to any integer value:
  1851.  
  1852.  
  1853.        SetErrorCode 2       'set the new error code
  1854.        PRINT ErrorCode%     'will always print "2"
  1855.  
  1856.  
  1857.     For more information see HANDLING ERRORS.
  1858.  
  1859.     See also ErrorCode.
  1860.  
  1861.  
  1862.  
  1863.  
  1864.     SetLocF
  1865.     -----------------------------------------------------------------
  1866.  
  1867.     DECLARE SUB SetLocF (Handle%, NewPtrLoc&)
  1868.  
  1869.     Parameters: Handle% = handle of file whose ptr will be reset
  1870.                 NewPtrLoc& = new location of pointer in the file
  1871.  
  1872.  
  1873.  
  1874.     SetLocF is a substitute for the statement form of SEEK.  You
  1875.     pass it the handle of the file whose pointer you want to set and
  1876.     the location of the byte where you want to set the file pointer
  1877.     (as an offset from the start of the file):
  1878.  
  1879.  
  1880.        SetLocF Handle%, 9000&
  1881.  
  1882.  
  1883.     The above code moves the file pointer in the file designated by
  1884.     Handle% to byte number 9000.  If subsequently you were to read
  1885.     from the file, byte 9000 would be the first byte read.  If you
  1886.     were to write to the file, byte 9000 would be the first byte
  1887.     written to.
  1888.  
  1889.     If you are unfamiliar with file pointers, see ABOUT FILE
  1890.     POINTERS.
  1891.  
  1892.     How SetLocF interprets the value of NewPtrLoc& may vary,
  1893.     depending on whether you have made a call to SetPtrBase.  By
  1894.     default, PBFiles considers the first byte of a file to be byte
  1895.     zero.  However, you may change this default to a 1-based system,
  1896.     using SetPtrBase.  Please see SetPtrBase for more details.
  1897.  
  1898.     It is possible to move the file pointer many bytes beyond the
  1899.     "end" byte of a disk file.  This is a valid position at which to
  1900.     write to a disk file -- in which case the disk file will be
  1901.     extended to include all the bytes falling between the previous
  1902.     "end" of the file and the byte where the pointer was located
  1903.     when the writing was initiated.
  1904.  
  1905.     If you try to read from a file when the pointer is located
  1906.     beyond its end, then PBFiles will simply return with no action
  1907.     taken and no error code.  If you try to read past the end byte
  1908.     of the file, PBFiles will read as far as the end byte of the
  1909.     file and stop.
  1910.  
  1911.     See also GetLocF.
  1912.  
  1913.  
  1914.  
  1915.  
  1916.     SetPtrBase
  1917.     -----------------------------------------------------------------
  1918.  
  1919.     DECLARE SUB SetPtrBase (PtrBase%)
  1920.  
  1921.     Parameters: PtrBase% = non-zero value sets pointer base to 1
  1922.  
  1923.  
  1924.  
  1925.     SetPtrBase sets the base value used by GetLocF& and SetLocF:
  1926.  
  1927.  
  1928.        SetPtrBase 1     'sets pointer base to 1
  1929.  
  1930.  
  1931.     Calling SetPtrBase with a zero sets the pointer base to zero.
  1932.     Calling SetPtrBase with any non-zero value sets the base value
  1933.     to 1. The default base value is zero.
  1934.  
  1935.     Normally, DOS defines the first byte of a file as byte 0 (zero).
  1936.     However, when Microsoft introduced BINARY file handling into
  1937.     BASIC, it chose to treat the first byte of a file as byte 1. To
  1938.     accomodate code written for this convention, PBFiles includes
  1939.     the commands SetPtrBase and GetPtrBase%.
  1940.  
  1941.     If you call SetPtrBase with a zero, PBFiles will act under the
  1942.     zero-based (DOS) convention.  This is also the PBFiles default.
  1943.     Under this convention, when the pointer is at the second byte of
  1944.     a file, GetLocF& will return 1, and if you want to set the
  1945.     pointer to the second byte you would use SetLocF 1.
  1946.  
  1947.     If you call SetPtrBase with a non-zero value, PBFiles will act
  1948.     under the one-based (Microsoft BASIC) convention.  Under this
  1949.     convention, when the pointer is at the second byte of a file,
  1950.     GetLocF& will return 2, and to set the pointer to the second
  1951.     byte you would use SetLocF 2.
  1952.  
  1953.     See also GetPtrBase.
  1954.  
  1955.  
  1956.  
  1957.  
  1958.     SizeF
  1959.     -----------------------------------------------------------------
  1960.  
  1961.     DECLARE FUNCTION SizeF& (Handle%)
  1962.  
  1963.     Parameters: Handle% = handle of file whose size you want
  1964.  
  1965.  
  1966.  
  1967.     SizeF& is a substitute for LOF.  It returns the length of a file
  1968.     that has been opened with OpenF%, as a long integer:
  1969.  
  1970.  
  1971.        HowBig& = SizeF&(Handle%)
  1972.  
  1973.  
  1974.     In the above code, SizeF& returns the size of the file
  1975.     designated by Handle% and assigns the value to the variable
  1976.     HowBig&.
  1977.  
  1978.     If an error occurs, SizeF& returns a zero.  Since zero is also a
  1979.     valid file length the only way to determine certainly if an
  1980.     error has occured is to call ErrorCode%.
  1981.  
  1982.  
  1983.  
  1984.     ********************************************************************
  1985.  
  1986.  
  1987.     WHY THIS FILE IS COPYRIGHTED
  1988.  
  1989.  
  1990.  
  1991.     Why is this file (PBFILES.DOC) copyrighted, while the source
  1992.     code file (PBFILES.ASM) is public domain?
  1993.  
  1994.     Simple.  I decided to place the source code for PBFiles into the
  1995.     public domain to you and other PowerBASIC programmers a tool you
  1996.     could freely use, learn from, alter or improve and then
  1997.     incorporate in your programs without constraint.  That is why
  1998.     PBFILES.ASM and PBFILES.OBJ are not copyrighted in any way.
  1999.  
  2000.     But I also wanted to retain some credit for the many hours of
  2001.     work PBFiles represents.  The problem was how to attach a
  2002.     copyright to PBFiles without attaching a copyright specifically
  2003.     to the source code.  The solution I reached was to copyright the
  2004.     documentation.
  2005.  
  2006.     The license which follows should not prevent you from using
  2007.     PBFiles in any legitimate way.
  2008.  
  2009.  
  2010.  
  2011.  
  2012.     LIMITED DISTRIBUTION LICENSE
  2013.  
  2014.  
  2015.     Brian McLaughlin (the "author"), grants to the holder (that's
  2016.     you) a limited license to copy, distribute or electronically
  2017.     transfer PBFILES.DOC (the "documentation") subject to the
  2018.     following terms and conditions:
  2019.  
  2020.     The documentation must be distributed whole and complete.  You
  2021.     must not alter or modify the contents of the documentation in
  2022.     any way.  Doing so will result in the immediate and automatic
  2023.     termination of this license.
  2024.  
  2025.     The documentation can only be distributed when accompanied by
  2026.     complete and unaltered copies of PBFILES.ASM, PBFILES.OBJ and
  2027.     PBFILES.BI (the "collateral files").  The copies of the
  2028.     collateral files which accompany the documentation must be
  2029.     identical to the collateral files which originally accompanied
  2030.     the documentation when it came into the possession of the
  2031.     license holder (you).
  2032.  
  2033.     Distribution of the documentation which fails to meet all these
  2034.     terms and conditions is prohibited and will result in immediate
  2035.     and automatic termination of this license.
  2036.  
  2037.  
  2038.     ──────────────────────────────────────────────────────────────────────
  2039.          Copyright 1994 Brian McLaughlin. All rights reserved.
  2040.  
  2041.